home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- *
- * NSSDC/CDF CDF library auxiliary functions.
- *
- * Version 1.0, 14-Feb-92, ST Systems (STX)
- *
- * Modification history:
- *
- * V1.0 14-Feb-92, J Love Original version. These functions were taken
- * out of `cdflib.c'.
- *
- ******************************************************************************/
-
- #include "cdflib.h"
-
- /******************************************************************************
- * Determine disposition of status.
- ******************************************************************************/
-
- void STATUSdispX (Tstatus, Pstatus)
- CDFstatus Tstatus;
- CDFstatus *Pstatus;
- {
- if (Tstatus != CDF_OK)
- if (Tstatus > CDF_OK) {
- if (*Pstatus >= CDF_OK) *Pstatus = Tstatus;
- }
- else
- *Pstatus = Tstatus;
- return;
- }
-
-
- /******************************************************************************
- * Do a STRing CoMPare Ignoring any Trailing Blanks.
- ******************************************************************************/
-
- int strcmpITB (string1, string2)
- /*const*/ char *string1;
- /*const*/ char *string2;
- {
- size_t len1, len2;
-
- for (len1 = strlen(string1); len1 > 0 && string1[len1 - 1] == ' '; len1--);
- for (len2 = strlen(string2); len2 > 0 && string2[len2 - 1] == ' '; len2--);
-
- if (len1 == len2)
- return strncmp (string1, string2, len1);
- else
- return strcmp (string1, string2);
-
- }
-
- /******************************************************************************
- * Free a CDFid's dynamically allocated memory.
- ******************************************************************************/
-
- void Free_CDFid (CDF)
- struct cdfSTRUCT *CDF;
- {
- void *ptr;
- struct varSTRUCT *Var;
- struct vixSTRUCT *Vix;
- struct attrSTRUCT *Attr;
- struct entrySTRUCT *Entry;
-
- Attr = CDF->attrHead; /* may be NULL if no attributes */
-
- while (Attr != NULL) {
- Entry = Attr->entryHead; /* may be NULL if no entries */
-
- while (Entry != NULL) {
- if (Entry->AEDR.Value != NULL) free (Entry->AEDR.Value);
- /* if an entry cannot exist
- without a value, checking
- first isn't necessary */
- ptr = (void *) Entry;
- Entry = Entry->entryNext;
- free (ptr);
- }
-
- ptr = (void *) Attr;
- Attr = Attr->attrNext;
- free (ptr);
- }
-
- Var = CDF->varHead;
- while (Var != NULL) {
- if (Var->products != NULL) free (Var->products);
- if (Var->hypIndices != NULL) free (Var->hypIndices);
- if (Var->hypProducts != NULL) free (Var->hypProducts);
- if (Var->hypTops != NULL) free (Var->hypTops);
- if (Var->VDR.DimVarys != NULL) free (Var->VDR.DimVarys);
- if (Var->VDR.FillValue != NULL) free (Var->VDR.FillValue);
-
- Vix = Var->vixHead;
- while (Vix != NULL) {
- ptr = (void *) Vix;
- Vix = Vix->vixNext;
- free (ptr);
- }
-
- ptr = (void *) Var;
- Var = Var->varNext;
- free (ptr);
- }
-
- if (CDF->indices != NULL) free (CDF->indices);
- if (CDF->counts != NULL) free (CDF->counts);
- if (CDF->intervals != NULL) free (CDF->intervals);
-
- if (CDF->GDR.DimSizes != NULL) free (CDF->GDR.DimSizes);
-
- free (CDF);
-
- return;
- }
-
- /******************************************************************************
- * Close a variable vector file to free a file pointer. The "current" variable
- * of a CDF could be the one being closed. Note that if a CDF is SINGLE file,
- * each variable's 'status' will be NO_VAR_FILE (so that variable will not be
- * considered for closing).
- ******************************************************************************/
-
- CDFstatus CloseLRUvar ()
- {
- CDFid id;
- struct varSTRUCT *Var;
- struct varSTRUCT *oldestVar = NULL;
- long oldest_access = _CDFpseudo_clock;
- int stat;
-
- for (id = 0; id < CDF_MAX_CDFS; id++)
- if (_CDFs[id] != NULL) {
- Var = _CDFs[id]->varHead;
- while (Var != NULL) {
- if (Var->status == VAR_OPENED) /* must be MULTI */
- if (Var->accessed_at < oldest_access) {
- oldest_access = Var->accessed_at;
- oldestVar = Var;
- }
- Var = Var->varNext;
- }
- }
-
- if (oldestVar != NULL) {
- stat = Close (oldestVar->fp);
- if (stat == EOF) return VAR_CLOSE_ERROR;
- oldestVar->status = VAR_CLOSED;
- }
-
- return CDF_OK;
- }
-
-
- /******************************************************************************
- * Open a file (closing a variable file if necessary).
- ******************************************************************************/
-
- File *OpenFile (filename, a_mode)
- /*const*/ char *filename;
- /*const*/ char *a_mode; /* access mode */
- {
- File *fp;
- CDFstatus Tstatus; /* temporary status */
-
- #if VIO_FOR_STREAM
- long n_buffers; /* number of CACHE buffers (if VIO) */
- #endif
-
- #if VIO_FOR_STREAM
- if (strstr(filename,".v") != NULL)
- n_buffers = nCACHE_BUFFERs_Vnn;
- else
- if (strstr(filename,".cdf") != NULL)
- n_buffers = nCACHE_BUFFERs_CDF;
- else
- if (strstr(filename,".cdh") != NULL)
- n_buffers = nCACHE_BUFFERs_CDH;
- else
- n_buffers = 0;
- #endif
-
- #if VIO_FOR_STREAM
- fp = Open (filename, a_mode, n_buffers);
- #else
- fp = Open (filename, a_mode);
- #endif
-
- if (fp == NULL) {
- Tstatus = CloseLRUvar ();
- if (Tstatus < CDF_WARN)
- fp = NULL;
- else
- #if VIO_FOR_STREAM
- fp = Open (filename, a_mode, n_buffers); /* try again */
- #else
- fp = Open (filename, a_mode); /* try again */
- #endif
- }
- return fp;
- }
-
-
- /******************************************************************************
- * Calculate parameters needed to access a variable.
- ******************************************************************************/
-
- void calcVarParms (CDF, Var)
- struct cdfSTRUCT *CDF;
- struct varSTRUCT *Var;
- {
- int i, j;
-
- /* Compute product array */
-
- if (bitclr(CDF->CDR.Flags,CDF_MAJORITY_BIT)) { /* COLUMN MAJOR */
- for (i = 0; i < CDF->GDR.NumDims; i++) {
- Var->products[i] = 1;
- for (j = 0; j < i; j++)
- if (Var->VDR.DimVarys[j])
- Var->products[i] *= CDF->GDR.DimSizes[j];
- }
- }
- else { /* ROW MAJOR */
- for (i = 0; i < CDF->GDR.NumDims; i++) {
- Var->products[i] = 1;
- for (j = i+1; j < CDF->GDR.NumDims; j++)
- if (Var->VDR.DimVarys[j])
- Var->products[i] *= CDF->GDR.DimSizes[j];
- }
- }
-
- Var->NvalueBytes = Var->VDR.NumElem * _CDFelemSizes[Var->VDR.DataType];
-
- Var->NphyRecValues = 1;
- Var->NvirtRecValues = 1;
-
- for (i = 0; i < CDF->GDR.NumDims; i++) {
- Var->NvirtRecValues *= CDF->GDR.DimSizes[i];
- if (Var->VDR.DimVarys[i]) Var->NphyRecValues *= CDF->GDR.DimSizes[i];
- }
-
- Var->NphyRecBytes = Var->NphyRecValues * Var->NvalueBytes;
- Var->NvirtRecBytes = Var->NvirtRecValues * Var->NvalueBytes;
-
- if (bitset(CDF->CDR.Flags,CDF_FORMAT_BIT))
- Var->defaultNextendRecs =
- Maximum((MIN_nEXTEND_BYTES_single-1)/Var->NphyRecBytes + 1,
- MIN_nEXTEND_RECS_single);
- else
- Var->defaultNextendRecs = MIN_nEXTEND_RECS_multi;
-
- return;
- }
-
- /******************************************************************************
- * Open a variable (file) for access. Only called if MULTI file.
- ******************************************************************************/
-
- CDFstatus OpenVar (CDF, Var)
- struct cdfSTRUCT *CDF;
- struct varSTRUCT *Var;
- {
- char tmp_filename[CDF_PATHNAME_LEN+6+1]; /* +6+1 for .Vnnnn and
- NUL-terminator */
- #if defined(unix) | defined(__MSDOS__)
- sprintf (tmp_filename, "%s.v%d", CDF->filename, Var->VDR.Num);
- #endif
-
- #if defined(vms)
- if (CDF->CDR.Version == 1)
- sprintf (tmp_filename, "%s.v%02d", CDF->filename, Var->VDR.Num + 1);
- else
- sprintf (tmp_filename, "%s.v%d", CDF->filename, Var->VDR.Num);
- #endif
-
- if (CDF->status == CDF_READ_WRITE) {
- #if defined(vms) | defined(__MSDOS__)
- Var->fp = OpenFile (tmp_filename,"r+b");
- #endif
- #if defined(unix)
- Var->fp = OpenFile (tmp_filename,"r+");
- #endif
- if (Var->fp == NULL) return VAR_OPEN_ERROR;
- }
- else { /* READ ONLY */
- #if defined(vms) | defined(__MSDOS__)
- Var->fp = OpenFile (tmp_filename,"rb");
- #endif
- #if defined(unix)
- Var->fp = OpenFile (tmp_filename,"r");
- #endif
- if (Var->fp == NULL) return VAR_OPEN_ERROR;
- }
-
- Var->status = VAR_OPENED;
-
- return CDF_OK;
- }
-
- /******************************************************************************
- * Fill the records for a variable.
- ******************************************************************************/
-
- CDFstatus FillRecords (CDF, Var, offset, Nrecs)
- struct cdfSTRUCT *CDF;
- struct varSTRUCT *Var;
- long offset;
- long Nrecs;
- {
- void *value;
- long Nbytes;
- size_t N;
- void *fill;
- long elemN; /* Element number within a value. */
- long Boffset; /* Byte offset within buffer. */
- long recN; /* Record number. */
- long valueN; /* Value number within a physical record. */
- int stat;
-
- /******************************************************************************
- * Determine fill value.
- ******************************************************************************/
-
- if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT))
- value = Var->VDR.FillValue;
- else {
- value = (void *) malloc (Var->NvalueBytes);
- if (value == NULL) return BAD_MALLOC;
- for (elemN = 0; elemN < Var->VDR.NumElem; elemN++) {
- memmove ((Byte *) value + elemN*_CDFelemSizes[Var->VDR.DataType],
- _CDFdefaultFillValues[Var->VDR.DataType],
- _CDFelemSizes[Var->VDR.DataType]);
- }
- }
-
- stat = Seek (Var->fp, offset, SEEK_SET);
- if (stat == EOF) {
- /* CLEAN UP */
- return VAR_WRITE_ERROR;
- }
-
- /******************************************************************************
- * Try to do it all at once.
- ******************************************************************************/
-
- Nbytes = Nrecs * Var->NphyRecBytes;
-
- #if defined(__MSDOS__)
- if (Nbytes < (long) 65536) {
- #endif
- fill = (void *) malloc (Nbytes);
- if (fill != NULL) {
- for (Boffset = 0; Boffset < Nbytes; Boffset += Var->NvalueBytes)
- memmove ((Byte *) fill + Boffset, value, Var->NvalueBytes);
-
- #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
- /* Do nothing. */
- #endif
-
- #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
- if (CDF->CDR.Encoding == NETWORK_ENCODING)
- xdr_encode (Var->VDR.DataType, Nbytes / _CDFelemSizes[Var->VDR.DataType],
- fill, fill);
- #endif
-
- N = putbytes (Nbytes, fill, Var->fp);
- if (N != Nbytes) {
- if (value != Var->VDR.FillValue) free (value);
- free (fill);
- return VAR_WRITE_ERROR;
- }
- if (value != Var->VDR.FillValue) free (value);
- free (fill);
- return CDF_OK;
- }
- #if defined(__MSDOS__)
- }
- #endif
-
- /******************************************************************************
- * That didn't work (no return yet), try one record at a time.
- ******************************************************************************/
-
- Nbytes = Var->NphyRecBytes;
-
- #if defined(__MSDOS__)
- if (Nbytes < (long) 65536) {
- #endif
- fill = (void *) malloc (Nbytes);
- if (fill != NULL) {
- for (Boffset = 0; Boffset < Nbytes; Boffset += Var->NvalueBytes)
- memmove ((Byte *) fill + Boffset, value, Var->NvalueBytes);
-
- #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
- /* Do nothing. */
- #endif
-
- #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
- xdr_encode (Var->VDR.DataType, Nbytes / _CDFelemSizes[Var->VDR.DataType],
- fill, fill);
- #endif
-
- for (recN = 0; recN < Nrecs; recN++) {
- N = putbytes (Nbytes, fill, Var->fp);
- if (N != Nbytes) {
- if (value != Var->VDR.FillValue) free (value);
- free (fill);
- return VAR_WRITE_ERROR;
- }
- }
- if (value != Var->VDR.FillValue) free (value);
- free (fill);
- return CDF_OK;
- }
- #if defined(__MSDOS__)
- }
- #endif
-
- /******************************************************************************
- * That didn't work (no return yet), try one value at a time.
- ******************************************************************************/
-
- Nbytes = Var->NvalueBytes;
-
- fill = (void *) malloc (Nbytes);
- if (fill != NULL) {
- memmove (fill, value, Var->NvalueBytes);
-
- #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
- /* Do nothing. */
- #endif
-
- #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
- xdr_encode (Var->VDR.DataType, Var->VDR.NumElem, fill, fill);
- #endif
-
- for (recN = 0; recN < Nrecs; recN++) {
- for (valueN = 0; valueN < Var->NphyRecValues; valueN++) {
- N = putbytes (Nbytes, fill, Var->fp);
- if (N != Nbytes) {
- if (value != Var->VDR.FillValue) free (value);
- free (fill);
- return VAR_WRITE_ERROR;
- }
- }
- }
- if (value != Var->VDR.FillValue) free (value);
- free (fill);
- return CDF_OK;
- }
-
- /******************************************************************************
- * That didn't work, there must be something seriously wrong.
- ******************************************************************************/
-
- return BAD_MALLOC;
- }
-
-
- /******************************************************************************
- * Allocate variable records.
- ******************************************************************************/
-
- CDFstatus AllocateRecords (CDF, Var, neededRecNum, override)
- struct cdfSTRUCT *CDF;
- struct varSTRUCT *Var;
- long neededRecNum;
- Boolean override; /* if TRUE, override minimum number of extend records */
- {
- long offset;
- long lastRecAllocated;
- long NneededRecs;
- long Nbytes;
- long Nrecs;
- Int32 RecordSize;
- Int32 RecordType;
- struct vixSTRUCT *Vix;
- struct vixSTRUCT *ntlVix; /* next-to-last Vix */
- CDFstatus Pstatus = CDF_OK;
- CDFstatus Tstatus;
- long i;
-
- /******************************************************************************
- * Check if MULTI file...
- ******************************************************************************/
-
- if (bitclr(CDF->CDR.Flags,CDF_FORMAT_BIT)) {
- if (override)
- NneededRecs = neededRecNum - Var->VDR.MaxRec;
- else
- NneededRecs = Maximum(neededRecNum - Var->VDR.MaxRec,
- (Var->VDR.NextendRecs == 0 ?
- Var->defaultNextendRecs : Var->VDR.NextendRecs));
- offset = (Var->VDR.MaxRec + 1) * Var->NphyRecBytes;
- Tstatus = FillRecords (CDF, Var, offset, NneededRecs);
- STATUSdisp (Tstatus, Pstatus);
- return Pstatus;
- }
-
- /******************************************************************************
- * Not MULTI file, must be SINGLE file. First check if the needed record is
- * already allocated (but not used yet)...
- ******************************************************************************/
-
- if (Var->vixTail != NULL) {
- Vix = Var->vixTail;
- if (Vix->VXR.FirstRec[Vix->VXR.NusedEntries-1] <= neededRecNum &&
- neededRecNum <= Vix->VXR.LastRec[Vix->VXR.NusedEntries-1])
- return Pstatus;
- }
-
- /******************************************************************************
- * Not allocated yet, allocate to at least the needed record.
- ******************************************************************************/
-
- if (Var->vixTail == NULL) {
- /************************************************************************
- * NO records yet for the variable.
- ************************************************************************/
-
- Vix = (struct vixSTRUCT *) malloc (sizeof(struct vixSTRUCT));
- if (Vix == NULL) return BAD_MALLOC;
- Var->vixHead = Vix;
- Var->vixTail = Vix;
- Vix->vixNext = (struct vixSTRUCT *) NULL;
-
- /*** set up VXR ***/
-
- Vix->VXRoffset = CDF->GDR.eof;
-
- Vix->VXR.RecordSize = VXR_BASE_SIZE + (3 * N_VXR_ENTRIES * sizeof(Int32));
- Vix->VXR.RecordType = VXR_;
- Vix->VXR.VXRnext = 0;
- Vix->VXR.Nentries = N_VXR_ENTRIES;
- Vix->VXR.NusedEntries = 0;
-
- Nbytes = N_VXR_ENTRIES * sizeof(Int32);
- Vix->VXR.FirstRec = (Int32 *) malloc (Nbytes);
- if (Vix->VXR.FirstRec == NULL) return BAD_MALLOC;
- Vix->VXR.LastRec = (Int32 *) malloc (Nbytes);
- if (Vix->VXR.LastRec == NULL) return BAD_MALLOC;
- Vix->VXR.VVRoffset = (Int32 *) malloc (Nbytes);
- if (Vix->VXR.VVRoffset == NULL) return BAD_MALLOC;
-
- for (i = 0; i < N_VXR_ENTRIES; i++) { /* start entry field at -1 */
- Vix->VXR.FirstRec[i] = -1;
- Vix->VXR.LastRec[i] = -1;
- Vix->VXR.VVRoffset[i] = -1;
- }
-
- CDF->GDR.eof += Vix->VXR.RecordSize;
-
- /*** point VDR to this VXR ***/
-
- Var->VDR.VXRhead = Vix->VXRoffset;
- Var->VDR.VXRtail = Vix->VXRoffset;
-
- /*** create VVR ***/
-
- if (override)
- Nrecs = neededRecNum + 1;
- else
- Nrecs = Maximum(neededRecNum + 1,
- (Var->VDR.NextendRecs == 0 ?
- Var->defaultNextendRecs : Var->VDR.NextendRecs));
-
- offset = CDF->GDR.eof;
-
- RecordSize = VVR_BASE_SIZE + (Nrecs * Var->NphyRecBytes);
- RecordType = VVR_;
-
- Seek (CDF->fp, offset, SEEK_SET);
- putint32 (CDF->fp, RecordSize);
- putint32 (CDF->fp, RecordType);
-
- Tstatus = FillRecords (CDF, Var, offset + VVR_BASE_SIZE, Nrecs);
- STATUSdisp (Tstatus, Pstatus);
-
- CDF->GDR.eof += RecordSize;
-
- Vix->VXR.FirstRec[0] = 0;
- Vix->VXR.LastRec[0] = Nrecs - 1;
- Vix->VXR.VVRoffset[0] = offset;
- Vix->VXR.NusedEntries = 1;
- }
- else {
- /************************************************************************
- * Already some records for the variable.
- ************************************************************************/
-
- Vix = Var->vixTail;
- lastRecAllocated = Vix->VXR.LastRec[Vix->VXR.NusedEntries-1];
-
- if (override)
- Nrecs = neededRecNum - lastRecAllocated;
- else
- Nrecs = Maximum(neededRecNum - lastRecAllocated,
- (Var->VDR.NextendRecs == 0 ?
- Var->defaultNextendRecs : Var->VDR.NextendRecs));
-
- /************************************************************************
- * First check if the last VVR can be extended (only if it is the last
- * internal record in the CDF).
- ************************************************************************/
-
- offset = Vix->VXR.VVRoffset[Vix->VXR.NusedEntries - 1];
- Seek (CDF->fp, offset, SEEK_SET);
- getint32 (CDF->fp, RecordSize);
-
- if (offset + RecordSize == CDF->GDR.eof) {
- RecordSize += Nrecs * Var->NphyRecBytes;
- Seek (CDF->fp, offset, SEEK_SET);
- putint32 (CDF->fp, RecordSize);
-
- Tstatus = FillRecords (CDF, Var, CDF->GDR.eof, Nrecs);
- STATUSdisp (Tstatus, Pstatus);
-
- CDF->GDR.eof += Nrecs * Var->NphyRecBytes;
- Vix->VXR.LastRec[Vix->VXR.NusedEntries - 1] += Nrecs;
-
- return Pstatus;
- }
-
- /************************************************************************
- * Can't extend last VVR, create another VVR.
- ************************************************************************/
-
- RecordSize = VVR_BASE_SIZE + (Nrecs * Var->NphyRecBytes);
- RecordType = VVR_;
-
- offset = CDF->GDR.eof;
-
- Seek (CDF->fp, offset, SEEK_SET);
- putint32 (CDF->fp, RecordSize);
- putint32 (CDF->fp, RecordType);
-
- Tstatus = FillRecords (CDF, Var, offset + VVR_BASE_SIZE, Nrecs);
- STATUSdisp (Tstatus, Pstatus);
-
- CDF->GDR.eof += RecordSize;
-
- /*** add entry to last VXR (or create new VXR if last VXR is full) ***/
-
- if (Vix->VXR.NusedEntries < Vix->VXR.Nentries) {
- Vix->VXR.FirstRec[Vix->VXR.NusedEntries] = lastRecAllocated + 1;
- Vix->VXR.LastRec[Vix->VXR.NusedEntries] = lastRecAllocated + Nrecs;
- Vix->VXR.VVRoffset[Vix->VXR.NusedEntries] = offset;
- Vix->VXR.NusedEntries++;
- }
- else { /* create a new VXR */
- ntlVix = Vix;
- Vix = (struct vixSTRUCT *) malloc (sizeof(struct vixSTRUCT));
- if (Vix == NULL) return BAD_MALLOC;
- Var->vixTail->vixNext = Vix;
- Var->vixTail = Vix;
- Vix->vixNext = (struct vixSTRUCT *) NULL;
-
- /*** set up VXR ***/
-
- Vix->VXRoffset = CDF->GDR.eof;
-
- Vix->VXR.RecordSize = VXR_BASE_SIZE + (3 * N_VXR_ENTRIES * sizeof(Int32));
- Vix->VXR.RecordType = VXR_;
- Vix->VXR.VXRnext = 0;
- Vix->VXR.Nentries = N_VXR_ENTRIES;
- Vix->VXR.NusedEntries = 0;
-
- Nbytes = N_VXR_ENTRIES * sizeof(Int32);
- Vix->VXR.FirstRec = (Int32 *) malloc (Nbytes);
- if (Vix->VXR.FirstRec == NULL) return BAD_MALLOC;
- Vix->VXR.LastRec = (Int32 *) malloc (Nbytes);
- if (Vix->VXR.LastRec == NULL) return BAD_MALLOC;
- Vix->VXR.VVRoffset = (Int32 *) malloc (Nbytes);
- if (Vix->VXR.VVRoffset == NULL) return BAD_MALLOC;
-
- for (i = 0; i < N_VXR_ENTRIES; i++) { /* start each field at -1 */
- Vix->VXR.FirstRec[i] = -1;
- Vix->VXR.LastRec[i] = -1;
- Vix->VXR.VVRoffset[i] = -1;
- }
-
- CDF->GDR.eof += Vix->VXR.RecordSize;
-
- /*** point next-to-last VXR and VDR to this VXR ***/
-
- ntlVix->VXR.VXRnext = Vix->VXRoffset;
- Var->VDR.VXRtail = Vix->VXRoffset;
-
- /*** add entry to new VXR ***/
-
- Vix->VXR.FirstRec[0] = lastRecAllocated + 1;
- Vix->VXR.LastRec[0] = lastRecAllocated + Nrecs;
- Vix->VXR.VVRoffset[0] = offset;
- Vix->VXR.NusedEntries = 1;
- }
- }
- return Pstatus;
- }
-
-
- /******************************************************************************
- * Calculate the EOF (byte offset) for a V2.0 CDF.
- ******************************************************************************/
-
- void calc_V20_eof (CDF)
- struct cdfSTRUCT *CDF;
- {
- struct varSTRUCT *Var;
- struct attrSTRUCT *Attr;
- struct entrySTRUCT *Entry;
- long EoF = 0;
-
- if (CDF->CDRoffset + CDF->CDR.RecordSize > EoF)
- EoF = CDF->CDRoffset + CDF->CDR.RecordSize;
-
- if (CDF->GDRoffset + CDF->GDR.RecordSize > EoF)
- EoF = CDF->GDRoffset + CDF->GDR.RecordSize;
-
- Var = CDF->varHead;
- while (Var != NULL) {
- if (Var->VDRoffset + Var->VDR.RecordSize > EoF)
- EoF = Var->VDRoffset + Var->VDR.RecordSize;
- Var = Var->varNext;
- }
-
- Attr = CDF->attrHead;
- while (Attr != NULL) {
- if (Attr->ADRoffset + Attr->ADR.RecordSize > EoF)
- EoF = Attr->ADRoffset + Attr->ADR.RecordSize;
-
- Entry = Attr->entryHead;
- while (Entry != NULL) {
- if (Entry->AEDRoffset + Entry->AEDR.RecordSize > EoF)
- EoF = Entry->AEDRoffset + Entry->AEDR.RecordSize;
-
- Entry = Entry->entryNext;
- }
-
- Attr = Attr->attrNext;
- }
-
- CDF->GDR.eof = EoF;
- return;
- }
-
- /******************************************************************************
- * Close the open files of the specified CDF.
- ******************************************************************************/
-
- CDFstatus CloseCDFfiles (CDF)
- struct cdfSTRUCT *CDF;
- {
- CDFstatus Pstatus = CDF_OK; /* pending status */
- CDFstatus Tstatus; /* temporary status */
- int stat;
- struct varSTRUCT *Var;
-
- if (CDF->status == CDF_READ_WRITE && CDF->CDR.Version == 2) {
- Tstatus = write_V2_header (CDF);
- STATUSdisp (Tstatus, Pstatus);
- }
-
- stat = Close (CDF->fp);
- if (stat == EOF) return CDF_CLOSE_ERROR;
-
- CDF->status = CDF_CLOSED;
-
- if (bitclr(CDF->CDR.Flags,CDF_FORMAT_BIT)) { /* if MULTI file */
- Var = CDF->varHead;
- while (Var != NULL) {
- if (Var->status == VAR_OPENED) {
- stat = Close (Var->fp);
- if (stat == EOF) return VAR_CLOSE_ERROR;
- Var->status = VAR_CLOSED;
- }
- Var = Var->varNext;
- }
- }
-
- return Pstatus;
- }
-
- /******************************************************************************
- * Close and then reopen a CDF for read/write access (it was opened with
- * read-only access initially).
- ******************************************************************************/
-
- CDFstatus ReopenCDFforWrite (CDF)
- struct cdfSTRUCT *CDF;
- {
- CDFstatus Pstatus = CDF_OK; /* pending status */
- CDFstatus Tstatus; /* temporary status */
- char openname[CDF_PATHNAME_LEN+4+1]; /* +4+1 for ".cdf" and NUL */
- struct varSTRUCT *Var;
-
- Tstatus = CloseCDFfiles (CDF);
- STATUSdisp (Tstatus, Pstatus);
-
- strcpy (openname, CDF->filename);
- strcat (openname, ".cdf");
-
- #if defined(vms) | defined(__MSDOS__)
- CDF->fp = OpenFile (openname, "r+b");
- #endif
- #if defined(unix)
- CDF->fp = OpenFile (openname, "r+");
- #endif
- if (CDF->fp == NULL) return NO_WRITE_ACCESS;
-
- CDF->status = CDF_READ_WRITE;
-
- /** if SINGLE, point the variable file pointers to the .CDF file pointer **/
-
- if (bitset(CDF->CDR.Flags,CDF_FORMAT_BIT)) {
- Var = CDF->varHead;
- while (Var != NULL) {
- Var->fp = CDF->fp;
- Var = Var->varNext;
- }
- }
-
- return Pstatus;
- }
-
-
- /******************************************************************************
- * Increment to next strip for Hyper function (ROW major CDF).
- ******************************************************************************/
-
- void incr_hypIndices_ROW (hypIndices, idim, indices, intervals, hypTops,
- dimVary, complete, physical, updim)
- long hypIndices[];
- long idim;
- long indices[];
- long intervals[];
- long hypTops[];
- long dimVary[];
- Boolean *complete; /* Assumed to be set FALSE by caller. */
- Boolean *physical;
- long *updim; /* Assumed to have proper value from last call. */
- {
- long dim_n;
- long startdim;
-
- if ( ! dimVary[*updim]) {
- if (hypIndices[*updim] < hypTops[*updim]) {
- hypIndices[*updim] += intervals[*updim];
- *physical = FALSE;
- return;
- }
- else
- startdim = *updim;
- }
- else
- startdim = idim;
-
- for (dim_n = startdim; dim_n >= 0; dim_n--)
- if (hypIndices[dim_n] < hypTops[dim_n]) {
- *updim = dim_n;
- hypIndices[*updim] += intervals[*updim];
-
- if (dimVary[*updim])
- *physical = TRUE;
- else
- *physical = FALSE;
-
- return;
- }
- else
- hypIndices[dim_n] = indices[dim_n];
-
- *complete = TRUE;
- return;
-
- }
-
- /******************************************************************************
- * Increment to next strip for Hyper function (COLumn major CDF).
- ******************************************************************************/
-
- void incr_hypIndices_COL (rank, hypIndices, idim, indices, intervals, hypTops,
- dimVary, complete, physical, updim)
- long rank;
- long hypIndices[];
- long idim;
- long indices[];
- long intervals[];
- long hypTops[];
- long dimVary[];
- Boolean *complete; /* Assumed to be set FALSE be caller. */
- Boolean *physical;
- long *updim; /* Assumed to have proper value from last call. */
- {
- long dim_n;
- long startdim;
-
- if ( ! dimVary[*updim]) {
- if (hypIndices[*updim] < hypTops[*updim]) {
- hypIndices[*updim] += intervals[*updim];
- *physical = FALSE;
- return;
- }
- else
- startdim = *updim;
- }
- else
- startdim = idim;
-
- for (dim_n = startdim; dim_n < rank; dim_n++)
- if (hypIndices[dim_n] < hypTops[dim_n]) {
- *updim = dim_n;
- hypIndices[*updim] += intervals[*updim];
-
- if (dimVary[*updim])
- *physical = TRUE;
- else
- *physical = FALSE;
-
- return;
- }
- else
- hypIndices[dim_n] = indices[dim_n];
-
- *complete = TRUE;
- return;
- }
-
- /******************************************************************************
- * Get bytes (strip) for HyperGet function. If on IBM PC, assumed that
- * 'striplen' is not greater than 64Kb.
- ******************************************************************************/
-
- CDFstatus HyperGetBytes (Var, offset, striplen, value)
- struct varSTRUCT *Var;
- long offset;
- long striplen;
- void *value;
- {
- size_t N;
-
- Seek (Var->fp, offset, SEEK_SET);
- N = getbytes (striplen, value, Var->fp);
- if (N != striplen) return VAR_READ_ERROR;
-
- DecodeBuffer (_CURcdf->CDR.Encoding, Var->VDR.DataType,
- striplen / _CDFelemSizes[Var->VDR.DataType], value);
-
- return CDF_OK;
- }
-
- /******************************************************************************
- * Put bytes (strip) for HyperPut function. If on IBM PC, assumed that
- * 'striplen' is not greater than 64Kb.
- ******************************************************************************/
-
- CDFstatus HyperPutBytes (Var, offset, striplen, value)
- struct varSTRUCT *Var;
- long offset;
- long striplen;
- void *value;
- {
- size_t N;
-
- Seek (Var->fp, offset, SEEK_SET);
-
- #if defined(sun) | defined(MIPSEB) | defined(IBMRS) | defined(HP)
- N = putbytes (striplen, value, Var->fp);
- if (N != striplen) return VAR_WRITE_ERROR;
- #endif
-
- #if defined(vax) | defined(MIPSEL) | defined(__IBMPC__)
- if (_CURcdf->CDR.Encoding == NETWORK_ENCODING) {
- void *tmpbuffer;
- long numValues, i, vsize;
-
- tmpbuffer = (void *) malloc (striplen);
- if (tmpbuffer != NULL) {
- xdr_encode (Var->VDR.DataType, striplen / _CDFelemSizes[Var->VDR.DataType],
- value, tmpbuffer);
- N = putbytes (striplen, tmpbuffer, Var->fp);
- if (N != striplen) {
- free (tmpbuffer);
- return VAR_WRITE_ERROR;
- }
- }
- else {
- vsize = Var->VDR.NumElem * _CDFelemSizes[Var->VDR.DataType];
- tmpbuffer = (void *) malloc (vsize);
- if (tmpbuffer == NULL) return BAD_MALLOC;
- numValues = striplen / vsize;
- for (i = 0; i < numValues; i++) {
- xdr_encode (Var->VDR.DataType, Var->VDR.NumElem,
- (Byte *) value + i*vsize, tmpbuffer);
- N = putbytes (vsize, tmpbuffer, Var->fp);
- if (N != vsize) {
- free (tmpbuffer);
- return VAR_WRITE_ERROR;
- }
- }
- }
- free (tmpbuffer);
- }
- else { /* host's encoding */
- N = putbytes (striplen, value, Var->fp);
- if (N != striplen) return VAR_WRITE_ERROR;
- }
- #endif
-
- return CDF_OK;
- }
-
- /******************************************************************************
- * Perform Hyper function.
- ******************************************************************************/
-
- CDFstatus HyperAccess (Var, value, row_major, get)
- struct varSTRUCT *Var;
- void *value;
- long row_major; /* TRUE if row major, FALSE if column major */
- long get; /* TRUE if hyperGet, FALSE if hyperPut */
- {
- Boolean complete, physical;
- long numDims, dimN, updim;
- long striplen, hypRecSize;
- long recTop, rec_n, movelen;
- long recOffset, offset, indicesOffset;
- long idim; /* the dimension to increment (all dimensions
- above/below it are read/written in their
- physical entirety) */
- Boolean one_access_idim; /* (imaginary) dimension to increment if only
- one physical read/write is necessary for
- each record */
- Boolean full_contig_records; /* TRUE if full contiguous records are being
- read/written */
- CDFstatus Pstatus = CDF_OK; /* pending status */
- CDFstatus Tstatus; /* temporary status */
- long Nelements;
- long Nvalues;
- long valueN;
- long elemN;
-
- numDims = _CURcdf->GDR.NumDims;
-
- if (row_major)
- one_access_idim = -1;
- else
- one_access_idim = numDims;
-
- if (numDims > 0) {
- if (row_major) {
- Var->hypProducts[numDims-1] = 1;
-
- for (dimN = numDims-2; dimN >= 0; dimN--)
- Var->hypProducts[dimN] = Var->hypProducts[dimN+1] *
- _CURcdf->counts[dimN+1];
-
- hypRecSize = (Var->hypProducts[0] * _CURcdf->counts[0]) *
- Var->NvalueBytes;
- }
- else {
- Var->hypProducts[0] = 1;
-
- for (dimN = 1; dimN < numDims; dimN++)
- Var->hypProducts[dimN] = Var->hypProducts[dimN-1] *
- _CURcdf->counts[dimN-1];
-
- hypRecSize = (Var->hypProducts[numDims-1] * _CURcdf->counts[numDims-1]) *
- Var->NvalueBytes;
- }
-
- for (dimN = 0; dimN < numDims; dimN++)
- Var->hypTops[dimN] = _CURcdf->indices[dimN] +
- (_CURcdf->counts[dimN] - 1) *
- _CURcdf->intervals[dimN];
- }
- else
- hypRecSize = Var->NvalueBytes;
-
- if (numDims > 0) {
- full_contig_records = TRUE;
- if (row_major) {
- for (idim = numDims-1; idim >= 0; idim--) {
- if (Var->VDR.DimVarys[idim]) {
- if (_CURcdf->counts[idim] < _CURcdf->GDR.DimSizes[idim]) {
- if (_CURcdf->intervals[idim] > 1) {
- striplen = Var->products[idim] * Var->NvalueBytes;
- }
- else {
- striplen = Var->products[idim] * _CURcdf->counts[idim] *
- Var->NvalueBytes;
- idim--;
- }
- full_contig_records = FALSE;
- break;
- }
- }
- else {
- if (_CURcdf->counts[idim] > 1) {
- striplen = Var->products[idim] * Var->NvalueBytes;
- full_contig_records = FALSE;
- break;
- }
- }
- }
- /*** if loop completed, idim = one_access_idim ***/
- }
- else {
- for (idim = 0; idim < numDims; idim++) {
- if (Var->VDR.DimVarys[idim]) {
- if (_CURcdf->counts[idim] < _CURcdf->GDR.DimSizes[idim]) {
- if (_CURcdf->intervals[idim] > 1) {
- striplen = Var->products[idim] * Var->NvalueBytes;
- }
- else {
- striplen = Var->products[idim] * _CURcdf->counts[idim] *
- Var->NvalueBytes;
- idim++;
- }
- full_contig_records = FALSE;
- break;
- }
- }
- else {
- if (_CURcdf->counts[idim] > 1) {
- striplen = Var->products[idim] * Var->NvalueBytes;
- full_contig_records = FALSE;
- break;
- }
- }
- }
- /*** if loop completed, idim = one_access_idim ***/
- }
- }
- else {
- idim = one_access_idim;
- full_contig_records = TRUE;
- }
-
- /******************************************************************************
- * Check if a contiguous strip of records...
- ******************************************************************************/
-
- if (full_contig_records && _CURcdf->recinterval == 1 &&
- bitset(Var->VDR.Flags,VAR_RECVARY_BIT) &&
- bitclr(_CURcdf->CDR.Flags,CDF_FORMAT_BIT)) {
- if (get) {
- long lastRec = _CURcdf->recnum + _CURcdf->reccount - 1;
- long beforeRecs =
- (_CURcdf->recnum <= Var->VDR.MaxRec ?
- (lastRec <= Var->VDR.MaxRec ?
- _CURcdf->reccount :
- Var->VDR.MaxRec - _CURcdf->recnum + 1) : 0);
-
- long afterRecs =
- (lastRec > Var->VDR.MaxRec ?
- (_CURcdf->recnum > Var->VDR.MaxRec ?
- _CURcdf->reccount : lastRec - Var->VDR.MaxRec) : 0);
-
- if (beforeRecs > 0) {
- offset = _CURcdf->recnum * Var->NphyRecBytes;
- Tstatus = HyperGetBytes (Var, offset, Var->NphyRecBytes * beforeRecs,
- value);
- STATUSdisp (Tstatus, Pstatus);
- }
-
- if (afterRecs > 0) {
- value = (Byte *) value + (beforeRecs * Var->NphyRecBytes);
- if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT)) {
- Nvalues = afterRecs * Var->NphyRecValues;
- for (valueN = 0; valueN < Nvalues; valueN++)
- memmove ((Byte *) value + valueN*Var->NvalueBytes,
- Var->VDR.FillValue, Var->NvalueBytes);
- }
- else {
- Nelements = afterRecs * Var->NphyRecValues * Var->VDR.NumElem;
- for (elemN = 0; elemN < Nelements; elemN++)
- memmove ((Byte *) value + elemN*_CDFelemSizes[Var->VDR.DataType],
- _CDFdefaultFillValues[Var->VDR.DataType],
- _CDFelemSizes[Var->VDR.DataType]);
- }
- STATUSdisp (VIRTUAL_RECORD_DATA, Pstatus);
- }
- }
- else { /*** put ***/
- offset = _CURcdf->recnum * Var->NphyRecBytes;
- Tstatus = HyperPutBytes (Var, offset,
- _CURcdf->reccount * Var->NphyRecBytes, value);
- STATUSdisp (Tstatus, Pstatus);
- }
- return Pstatus;
- }
-
- /******************************************************************************
- * ...not a contiguous strip of records, do it one record at a time.
- ******************************************************************************/
-
- if (full_contig_records) striplen = Var->NphyRecBytes;
-
- recTop = _CURcdf->recnum + (_CURcdf->reccount-1) * _CURcdf->recinterval;
-
- for (rec_n = _CURcdf->recnum; rec_n <= recTop; rec_n += _CURcdf->recinterval)
- if (bitset(Var->VDR.Flags,VAR_RECVARY_BIT) || rec_n == _CURcdf->recnum) {
- /*************************************************************************
- * Don't propagate if the record variance is VARY or if this is the first
- * record (VARY or NOVARY). If the latter case, we have to get at least
- * the first record (and then propagate the remaining records if the record
- * variance is NOVARY).
- *************************************************************************/
-
- if (get && rec_n > Var->VDR.MaxRec &&
- !(bitclr(Var->VDR.Flags,VAR_RECVARY_BIT) && Var->VDR.MaxRec != -1)) {
- /*********************************************************************
- * This variable doesn't have as many physical records actually written
- * as does the entire CDF have 'virtual' records (meaning that SOME
- * variable has that many physical records). There is a special case
- * to be checked for. If the record variance is NOVARY and there has
- * been a record written (record 0), then we need to read the first
- * record (record 0) regardless of the first record actually requested.
- *********************************************************************/
-
- if (bitset(Var->VDR.Flags,VAR_FILLVALUE_BIT)) {
- long Nvalues;
- Nvalues = hypRecSize / Var->NvalueBytes;
- for (valueN = 0; valueN < Nvalues; valueN++)
- memmove ((Byte *) value + valueN*Var->NvalueBytes,
- Var->VDR.FillValue, Var->NvalueBytes);
- }
- else {
- long Nelements;
- Nelements = hypRecSize / _CDFelemSizes[Var->VDR.DataType];
- for (elemN = 0; elemN < Nelements; elemN++)
- memmove ((Byte *) value + elemN*_CDFelemSizes[Var->VDR.DataType],
- _CDFdefaultFillValues[Var->VDR.DataType],
- _CDFelemSizes[Var->VDR.DataType]);
- }
- value = (Byte *) value + hypRecSize;
- STATUSdisp (VIRTUAL_RECORD_DATA, Pstatus);
- }
- else {
- /*********************************************************************
- * Read/write from/to variable file. A record offset of zero is used
- * if the record variance is NOVARY.
- *********************************************************************/
-
- if (bitset(Var->VDR.Flags,VAR_RECVARY_BIT)) {
- if (bitclr(_CURcdf->CDR.Flags,CDF_FORMAT_BIT))
- recOffset = rec_n * Var->NphyRecBytes;
- else
- SINGLErecOffsetB (Var, rec_n, recOffset);
- }
- else {
- if (bitclr(_CURcdf->CDR.Flags,CDF_FORMAT_BIT))
- recOffset = 0;
- else
- SINGLErecOffsetB (Var, 0, recOffset);
- }
-
- if (idim != one_access_idim) {
- for (dimN = 0; dimN < numDims; dimN++)
- Var->hypIndices[dimN] = _CURcdf->indices[dimN];
-
- complete = FALSE;
- physical = TRUE;
- updim = idim;
-
- while ( ! complete) {
- if (physical) {
- INDICESoffsetB (numDims, Var, Var->hypIndices,
- indicesOffset);
- offset = recOffset + indicesOffset;
-
- if (get)
- Tstatus = HyperGetBytes (Var, offset, striplen, value);
- else
- Tstatus = HyperPutBytes (Var, offset, striplen, value);
- STATUSdisp (Tstatus, Pstatus);
-
- value = (Byte *) value + striplen;
- }
- else {
- movelen = Var->hypProducts[updim] * Var->NvalueBytes;
- if (get) memmove (value, (Byte *) value - movelen, movelen);
- value = (Byte *) value + movelen;
- }
-
- if (row_major)
- incr_hypIndices_ROW (Var->hypIndices, idim,
- _CURcdf->indices, _CURcdf->intervals,
- Var->hypTops, Var->VDR.DimVarys,
- &complete, &physical, &updim);
- else
- incr_hypIndices_COL (numDims, Var->hypIndices, idim,
- _CURcdf->indices, _CURcdf->intervals,
- Var->hypTops, Var->VDR.DimVarys,
- &complete, &physical, &updim);
- }
- }
- else {
- if (full_contig_records)
- offset = recOffset;
- else {
- INDICESoffsetB (numDims, Var, _CURcdf->indices, indicesOffset);
- offset = recOffset + indicesOffset;
- }
- if (get)
- Tstatus = HyperGetBytes (Var, offset, striplen, value);
- else
- Tstatus = HyperPutBytes (Var, offset, striplen, value);
- STATUSdisp (Tstatus, Pstatus);
- value = (Byte *) value + striplen;
- }
- }
- }
- else {
- /************************************************************************
- * Propagate rather than actually reading from the variable file (if this
- * is a HyperGet - if a HyperPut, just skip over the data in the buffer).
- ************************************************************************/
-
- if (get) memmove (value, (Byte *) value - hypRecSize, hypRecSize);
- value = (Byte *) value + hypRecSize;
- }
-
- return Pstatus;
- }
-